﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using com.IronOne.BoardPACWinAppBO.General;
using com.IronOne.BoardPACWinAppBO.Paper;
using com.IronOne.BoardPACWinAppBO.Settings;
using com.IronOne.BoardPACWinAppBO.Sync;
using com.IronOne.BoardPACWinAppDAO.Agenda;
using com.IronOne.BoardPACWinAppDAO.Init;
using com.IronOne.BoardPACWinAppDAO.Sync;
using com.IronOne.BoardPACWinAppService.Xml;
using com.IronOne.BoardPACWinAppUtil.Enums;
using com.IronOne.BoardPACWinAppUtil.Util;
using GalaSoft.MvvmLight.Messaging;

namespace com.IronOne.BoardPACWinAppService.Sync
{
    public class SyncService : ISyncService
    {
        private readonly IAgendaDAO _agendaDAO;
        private readonly IInitDAO _initDAO;
        private readonly ISyncDAO _syncDAO;

        public SyncService()
        {
            _initDAO = new InitDAO();
            _syncDAO = new SyncDAO();
            _agendaDAO = new AgendaDAO();
        }

        public async Task<AppSettingModel> ReadAppSettingsFromDb()
        {
            try
            {
                return await _initDAO.SelectAllAppSettings();
            }
            catch (Exception)
            {
                return null;
            }
        }

        public async Task<ResponseDataModel> DataDownload()
        {
            try
            {
                var sdm = await _syncDAO.GetSyncHttpPostParameters();
                var postData = PrepareParameterBundle(sdm);
                var postAnnotData = PrepareAnnotateParameterBundle(sdm);

                #region Commented

                //Sync 1
                /*Dictionary<string, string> postData = PrepareParameterBundle(sdm);
                ResponseDataModel responseModel1 = await RequestManager.CreateRequest(postData, RequestURL.DataDownload, ApplicationConstants.RequestType.POST);

                //Sync 2
                Dictionary<string, string> postAnnotData = PrepareAnnotateParameterBundle(sdm);
                ResponseDataModel responseModel2 = await RequestManager.CreateRequest(postAnnotData, RequestURL.DownloadAnnotationData, ApplicationConstants.RequestType.GET);

                if (responseModel1.IsError) return responseModel1;
                if (responseModel2.IsError) return responseModel2;

                DownloadDataModel ddm1 = XmlToModelMapper.SyncDownloadDataModelMapper(responseModel1.Data.ToString());
                DownloadDataModel ddm2 = XmlToModelMapper.SyncDownloadDataModelMapper(responseModel2.Data.ToString());

                await SaveProfilePicturesToFileSystem(ddm1);
                //bool isSuccess = await SaveProfilePicturesToFileSystem(ddm1);
                ResponseDataModel resModel1 = await _syncDAO.SaveSyncDownloadDataToLocalDb(ddm1);
                ResponseDataModel resModel2 = await _syncDAO.SaveSyncDownloadDataToLocalDb(ddm2);

                bool succ = await _initDAO.SyncTranckingInfoToGeneralDb(responseModel2);

                timerObj.Stop();
                int ss = (int)timerObj.ElapsedMilliseconds;

                return resModel1;*/

                #endregion

                #region Task.WhenAll

                var resultModels1 = await Task.WhenAll
                    (
                        RequestManager.CreateRequest(postData, RequestURL.DataDownload,
                            ApplicationConstants.RequestType.POST),
                        RequestManager.CreateRequest(postAnnotData, RequestURL.DownloadAnnotationData,
                            ApplicationConstants.RequestType.GET)
                    );

                #endregion

                if (resultModels1[0].IsError) return resultModels1[0];
                if (resultModels1[1].IsError) return resultModels1[1];

                var ddm1 = XmlToModelMapper.SyncDownloadDataModelMapper(resultModels1[0].Data.ToString());
                var ddm2 = XmlToModelMapper.SyncDownloadDataModelMapper(resultModels1[1].Data.ToString());

                #region Task.WhenAll

                var resultModels2 = await Task.WhenAll
                    (
                        SaveProfilePicturesToFileSystem(ddm1),
                        _syncDAO.SaveSyncDownloadDataToLocalDb(ddm1),
                        _syncDAO.SaveSyncDownloadDataToLocalDb(ddm2),
                        _initDAO.SyncTranckingInfoToGeneralDb(resultModels1[1])
                    );

                #endregion

                return resultModels1[0];
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<ResponseDataModel> DataUpload()
        {
            try
            {
                var ldm = await _syncDAO.GetLogRecords();

                var responseModel = new ResponseDataModel();
                ResponseDataModel responseModelSuccess = null;
                foreach (var logModel in ldm)
                {
                    switch (logModel.Action)
                    {
                        case ApplicationConstants.LogActions.AddMeetingComment:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.AddMeetingComment + "&RefId=" + logModel.MeetingId + "&type=2",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.AddPaperComment:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.AddPaperComments + "&RefId=" + logModel.PaperId + "&type=3",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UpdateIndividualPresence:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.UpdateBoardMemberParticipation + "&RefId=" + logModel.MeetingId +
                                        "&type=2", ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UpdateMeetingPresence:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.UpdateMeetingPresence + "&RefId=" + logModel.MeetingId + "&type=2",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UpdateMeetingNote:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.UpdateMeetingNote + "&RefId=" + logModel.MeetingId + "&type=2",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UpdatePaperPresentStatus:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.UpdatePaperPresentStatus + "&RefId=" + logModel.PaperId + "&type=3",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UpdateUserApprovals:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.UpdateUserApprovals + "&RefId=" + logModel.PaperId + "&type=3",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UpdateViewedPaperComments:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.UpdateViewedComments + "&RefId=" + logModel.PaperId + "&type=3",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UpdateViewedMeetingComments:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.UpdateViewedComments + "&RefId=" + logModel.MeetingId + "&type=2",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UpdateViewedPaper:
                            responseModel =
                                await
                                    RequestManager.CreateRequest(GetPostData(logModel),
                                        RequestURL.UpdateViewedPaper + "&RefId=" + logModel.PaperId + "&type=3",
                                        ApplicationConstants.RequestType.POST);
                            break;
                        case ApplicationConstants.LogActions.UploadAnnotation:
                            responseModel =
                                await
                                    RequestManager.CreateRequest2(GetPostData(logModel),
                                        RequestURL.UploadAnnotation + "&RefId=" + logModel.PaperId + "&type=3",
                                        logModel.Info);
                            break;
                    }

                    //Data uploded successfully. So entry will be removed from the local db
                    if (!responseModel.IsError)
                    {
                        var result = await _syncDAO.DeleteLogRecord(logModel.LogId);
                        responseModelSuccess = new ResponseDataModel { IsError = false };
                    }
                    else
                    {
                        if (responseModel.ErrorCode == null || !responseModel.ErrorCode.Equals("err_99")) continue;

                        var paperName = await _syncDAO.GetPaperName(logModel.PaperId.Value);
                        var result = await _syncDAO.DeleteLogRecord(logModel.LogId);

                        var mdm = new MessageDataModel
                        {
                            MessageData = string.Format(responseModel.ErrorMessage, paperName)
                        };
                        var message = new NotificationMessage<MessageDataModel>(mdm,
                            MessageCodes.UPDATE_USER_APPROVAL_ERROR);
                        Messenger.Default.Send(message);
                    }
                }

                return responseModelSuccess ?? responseModel;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<List<PaperModel>> GetPapersToDownload()
        {
            try
            {
                return await _agendaDAO.GetPapersToDownload();
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<ResponseDataModel> DocumentDownload(int meetingId = 0, int documentType = 0, int paperId = 0,
            int versionId = 0)
        {
            var rdm = new ResponseDataModel();
            try
            {
                var postData = new Dictionary<string, string>();

                //If db deleted and download papers still exists
                var isAvailable = await _agendaDAO.CheckFileExistOnPdfFolder(paperId, versionId);
                if (isAvailable)
                {
                    await _syncDAO.MarkPaperAsDownloaded(paperId, versionId);
                    return rdm;
                }

                if (documentType == (int)PaperTypes.NewsItem || documentType == (int)PaperTypes.SharedDoc)
                {
                    postData.Add("itemId", paperId.ToString());
                    postData.Add("itemType", documentType.ToString());
                    postData.Add("decrypt", "false");
                    postData.Add("refId", paperId.ToString());

                    rdm =
                        await
                            RequestManager.CreateRequest(postData, RequestURL.NewsOrSharedItemDownload,
                                ApplicationConstants.RequestType.GET);
                }
                else
                {
                    postData.Add("meetingId", meetingId.ToString());
                    postData.Add("documentType", documentType.ToString());
                    postData.Add("paperId", paperId.ToString());
                    postData.Add("versionId", versionId.ToString());
                    postData.Add("decrypt", "false");
                    postData.Add("type", "3");
                    postData.Add("refId", paperId.ToString());

                    rdm =
                        await
                            RequestManager.CreateRequest(postData, RequestURL.DocumentDownload,
                                ApplicationConstants.RequestType.GET);
                }

                var fileData = (byte[])rdm.Data;
                if (fileData.Length < 500)
                {
                    var result = Encoding.UTF8.GetString(fileData, 0, fileData.Length);
                    if (result.ToLower().Contains("not authorized"))
                    {
                        //Hope this is OK. - Suren
                        rdm.IsError = false;
                        rdm.ErrorMessage = result;
                        return rdm;
                    }
                }

                if (!rdm.IsError)
                {
                    var isFileSavingSuccess = await SaveEncryptedFile((byte[])rdm.Data, paperId, versionId);
                    return rdm;
                }
            }
            catch (Exception)
            {
                throw;
            }
            return rdm;
        }

        public async Task<List<PaperModel>> GetAnnotationFilesToDownload()
        {
            try
            {
                try
                {
                    return await _agendaDAO.GetAnnotationFilesToDownload();
                }
                catch (Exception)
                {
                    throw;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<ResponseDataModel> AnnotationDownload(PaperModel annotModel)
        {
            var rdm = new ResponseDataModel();
            try
            {
                //If db deleted and download papers still exists
                var isAvailable =
                    await
                        _agendaDAO.CheckAnnotationFileExistOnReceivedFolder(annotModel.PaperId, annotModel.VersionId,
                            annotModel.AsAnnotationShareId);
                if (isAvailable)
                {
                    await
                        _syncDAO.MarkAnnotationFileAsDownloaded(annotModel.PaperId, annotModel.VersionId,
                            annotModel.AsAnnotationShareId);
                    return rdm;
                }

                var postData = new Dictionary<string, string>();
                postData.Add("aSharedId", annotModel.AsAnnotationShareId.ToString());
                postData.Add("type", "3");
                postData.Add("refId", annotModel.PaperId.ToString());
                rdm =
                    await
                        RequestManager.CreateRequest(postData, RequestURL.DownloadAnnotation,
                            ApplicationConstants.RequestType.GET);

                var saveFile = true;
                var fileData = (byte[])rdm.Data;
                if (fileData.Length > 0)
                {
                    var result = Encoding.UTF8.GetString(fileData, 0, fileData.Length);
                    if (result.ToLower().Contains("not authorized"))
                    {
                        saveFile = false;
                        //Hope this is OK. - Suren
                        rdm.IsError = true;
                        rdm.ErrorMessage = result;
                        //return rdm;
                    }
                    if (!result.ToLower().Contains("<annots>"))
                    {
                        saveFile = true;
                        //Hope this is OK. - Suren
                        rdm.IsError = false;
                        rdm.ErrorMessage = "Annotations are not supported on the Windows platform";
                        //return rdm;
                    }
                }

                if (saveFile)
                {
                    var isFileSavingSuccess =
                        await
                            SaveAnnotationFile((byte[])rdm.Data, annotModel.PaperId, annotModel.VersionId,
                                annotModel.AsAnnotationShareId);
                    return rdm;
                }
            }
            catch (Exception)
            {
                throw;
            }
            return rdm;
        }

        public async Task<ResponseDataModel> AnnotationRestore(PaperModel model)
        {
            var rdm = new ResponseDataModel();
            try
            {
                //If db deleted and download papers still exists
                /*var isAvailable =
                    await
                        _agendaDAO.CheckRestoreAnnotationFileExist(model.PaperId, model.VersionId);
                if (isAvailable)
                {
                    await
                        _agendaDAO.UpdateRestoreAnnotationTable(model.RefId, PaperDownloadStatuses.Downloded);
                    return rdm;
                }*/

                var postData = new Dictionary<string, string>();
                postData.Add("aSharedId", model.RefId.ToString());  //NOTE: RefId contains the BackupId
                postData.Add("type", "3");
                postData.Add("refId", model.PaperId.ToString());
                rdm =
                    await
                        RequestManager.CreateRequest(postData, RequestURL.DownloadAnnotation,
                            ApplicationConstants.RequestType.GET);

                var saveFile = true;
                var fileData = (byte[])rdm.Data;
                if (fileData.Length > 0)
                {
                    var result = Encoding.UTF8.GetString(fileData, 0, fileData.Length);
                    if (result.ToLower().Contains("not authorized"))
                    {
                        saveFile = false;
                        //Hope this is OK. - Suren
                        rdm.IsError = true;
                        rdm.ErrorMessage = result;
                        //return rdm;
                    }
                    if (!result.ToLower().Contains("<annots>"))
                    {
                        saveFile = true;
                        //Hope this is OK. - Suren
                        rdm.IsError = false;
                        rdm.ErrorMessage = "Annotations are not supported on the Windows platform";
                        //return rdm;
                    }
                }

                if (saveFile)
                {
                    var isFileSavingSuccess =
                        await
                            SaveRestoreAnnotationFile((byte[])rdm.Data, model.PaperId, model.VersionId);
                    return rdm;
                }
            }
            catch (Exception)
            {
                throw;
            }
            return rdm;
        }

        /// <summary>
        ///     When encrypted file downloaded from server, it need to be saved in the device. following method
        ///     does that and also updates a flag on the Paper table as well.
        /// </summary>
        /// <param name="fileData"></param>
        /// <param name="paperId"></param>
        /// <param name="versionId"></param>
        /// <returns></returns>
        public async Task<bool> SaveEncryptedFile(byte[] fileData, int paperId = 0, int versionId = 0)
        {
            try
            {
                await SaveCommon(fileData, paperId, versionId);
                await _syncDAO.MarkPaperAsDownloaded(paperId, versionId);

                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<bool> SaveEncryptedPastPaperFile(byte[] fileData, int paperId = 0, int versionId = 0)
        {
            try
            {
                await SaveCommon(fileData, paperId, versionId);
                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<List<LogDataModel>> GetLogRecords()
        {
            try
            {
                return await _syncDAO.GetLogRecords();
            }
            catch (Exception)
            {
                return null;
            }
        }

        private async Task SaveCommon(byte[] fileData, int paperId, int versionId)
        {
            try
            {
                var fileName = paperId + "_" + Global.UserId + "_" + versionId;
                var userFolder =
                    await
                        StorageFolder.GetFolderFromPathAsync(Path.Combine(ApplicationData.Current.LocalFolder.Path,
                            Global.UserId.ToString()));
                var documentsFolder =
                    await userFolder.CreateFolderAsync(ApplicationConstants.PDF, CreationCollisionOption.OpenIfExists);
                var pdfFile = await documentsFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

                using (var ostream = await pdfFile.OpenStreamForWriteAsync())
                {
                    await ostream.WriteAsync(fileData, 0, fileData.Length);
                    await ostream.FlushAsync();
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private async Task<ResponseDataModel> SaveProfilePicturesToFileSystem(DownloadDataModel ddm)
        {
            var rdm = new ResponseDataModel();
            try
            {
                if (ddm.ImgType == null) return rdm;

                var localFolder = ApplicationData.Current.LocalFolder;
                //Create Profile folder inside local folder
                var picFolder = await localFolder.CreateFolderAsync(ddm.ImgType, CreationCollisionOption.OpenIfExists);
                foreach (var item in ddm.ImageData)
                {
                    var sampleFile =
                        await picFolder.CreateFileAsync(item.Key + ".png", CreationCollisionOption.ReplaceExisting);
                    var bytes = Convert.FromBase64String(item.Value);
                    await FileIO.WriteBytesAsync(sampleFile, bytes);
                }
                return rdm;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<bool> SaveAnnotationFile(byte[] fileData, int paperId = 0, int versionId = 0,
            int annotationShareId = 0)
        {
            try
            {
                var fileName = paperId + "_" + Global.UserId + "_" + versionId + "_" + annotationShareId +
                               ApplicationConstants.ANNOTATEEXT;
                var receivedFolder = await Utility.GetShareReceivedFolder();
                var pdfFile = await receivedFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

                using (var ostream = await pdfFile.OpenStreamForWriteAsync())
                {
                    await ostream.WriteAsync(fileData, 0, fileData.Length);
                    await ostream.FlushAsync();
                }

                await _syncDAO.MarkAnnotationFileAsDownloaded(paperId, versionId, annotationShareId);

                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<bool> SaveRestoreAnnotationFile(byte[] fileData, int paperId = 0, int versionId = 0)
        {
            try
            {
                var fileName = paperId + "_" + Global.UserId + "_" + versionId + ApplicationConstants.ANNOTATEEXT;
                var originalFolder = await Utility.GetShareOriginalFolder();
                var pdfFile = await originalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

                using (var ostream = await pdfFile.OpenStreamForWriteAsync())
                {
                    await ostream.WriteAsync(fileData, 0, fileData.Length);
                    await ostream.FlushAsync();
                }

                //await _agendaDAO.UpdateRestoreAnnotationTable(paperId, PaperDownloadStatuses.Downloded);

                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        ///     DataUploadService()'s post data generater
        /// </summary>
        /// <param name="logModel"></param>
        /// <returns></returns>
        private Dictionary<string, string> GetPostData(LogDataModel logModel)
        {
            var postData = new Dictionary<string, string>();

            try
            {
                switch (logModel.Action)
                {
                    #region MyRegion

                    case ApplicationConstants.LogActions.AddMeetingComment:

                        var meetingComment = logModel.Data.Split(ApplicationConstants.Seperator)[0];
                        var meetingUserList = logModel.Data.Split(ApplicationConstants.Seperator)[1];

                        postData.Add("uniqueId", logModel.UpdateId);
                        postData.Add("memberId", logModel.MemberId.ToString());
                        postData.Add("meetingId", logModel.MeetingId.ToString());
                        postData.Add("data", meetingComment);
                        postData.Add("userlist", meetingUserList);
                        break;

                    case ApplicationConstants.LogActions.AddPaperComment:

                        var paperComment = logModel.Data.Split(ApplicationConstants.Seperator)[0];
                        var paperUserList = logModel.Data.Split(ApplicationConstants.Seperator)[1];

                        postData.Add("uniqueId", logModel.UpdateId);
                        postData.Add("memberId", logModel.MemberId.ToString());
                        postData.Add("paperId", logModel.PaperId.ToString());
                        postData.Add("data", paperComment);
                        postData.Add("userlist", paperUserList);
                        break;

                    case ApplicationConstants.LogActions.UpdateIndividualPresence:
                        postData.Add("uniqueId", logModel.UpdateId);
                        postData.Add("data", logModel.Data);
                        postData.Add("memberId", logModel.MemberId.ToString());
                        postData.Add("meetingId", logModel.MeetingId.ToString());
                        break;

                    case ApplicationConstants.LogActions.UpdateMeetingPresence:
                        postData.Add("uniqueId", logModel.UpdateId);
                        postData.Add("meetingId", logModel.MeetingId.ToString());
                        postData.Add("data", logModel.Data);
                        break;

                    case ApplicationConstants.LogActions.UpdateMeetingNote:
                        postData.Add("memberid", logModel.MemberId.ToString());
                        postData.Add("meetingId", logModel.MeetingId.ToString());
                        postData.Add("data", logModel.Data);
                        postData.Add("refid", logModel.MeetingId.ToString());
                        postData.Add("type", "2");
                        break;

                    case ApplicationConstants.LogActions.UpdatePaperPresentStatus:
                        postData.Add("meetingId", logModel.MeetingId.ToString());
                        postData.Add("paperId", logModel.PaperId.ToString());
                        break;

                    case ApplicationConstants.LogActions.UpdateUserApprovals:
                        string paperApprovalStat = null;
                        string paperApprovalComment = null;

                        if (logModel.Data.Contains(ApplicationConstants.Seperator))
                        {
                            paperApprovalStat = logModel.Data.Split(ApplicationConstants.Seperator)[0];
                            paperApprovalComment = logModel.Data.Split(ApplicationConstants.Seperator)[1];
                        }
                        else //Approval without comment
                        {
                            paperApprovalStat = logModel.Data;
                        }

                        postData.Add("uniqueId", logModel.UpdateId);
                        postData.Add("memberId", logModel.MemberId.ToString());
                        postData.Add("paperId", logModel.PaperId.ToString());
                        postData.Add("data", paperApprovalStat);
                        postData.Add("comment", paperApprovalComment);
                        break;

                    case ApplicationConstants.LogActions.UpdateViewedPaperComments:
                        postData.Add("memberId", logModel.MemberId.ToString());
                        postData.Add("operation", logModel.Action);
                        postData.Add("paperId", logModel.PaperId.ToString());
                        break;

                    case ApplicationConstants.LogActions.UpdateViewedMeetingComments:
                        postData.Add("memberId", logModel.MemberId.ToString());
                        postData.Add("operation", logModel.Action);
                        postData.Add("meetingId", logModel.MeetingId.ToString());
                        break;

                    case ApplicationConstants.LogActions.UpdateBoardMemberParticipation:
                        postData.Add("meetingId", logModel.MeetingId.ToString());
                        postData.Add("data", logModel.Data);
                        postData.Add("uniqueId", logModel.UpdateId);
                        break;

                    case ApplicationConstants.LogActions.UpdateViewedPaper:
                        postData.Add("memberId", logModel.MemberId.ToString());
                        postData.Add("paperId", logModel.PaperId.ToString());
                        postData.Add("data", logModel.Data);
                        break;
                    case ApplicationConstants.LogActions.UploadAnnotation:
                        postData.Add("memberId", logModel.MemberId.ToString());
                        postData.Add("PaperId", logModel.PaperId.ToString());
                        postData.Add("iPadUniqueID", logModel.UpdateId);
                        postData.Add("VersionId", logModel.Status);
                        postData.Add("data", logModel.Data);
                        break;

                    #endregion
                }
            }
            catch (Exception)
            {
                throw;
            }
            return postData;
        }

        /// <summary>
        ///     Sync 1
        /// </summary>
        /// <param name="sdm"></param>
        /// <returns></returns>
        private Dictionary<string, string> PrepareParameterBundle(SyncDataModel sdm)
        {
            var postData = new Dictionary<string, string>();
            try
            {
                //postData.Add("UserTimeStamp", "");  //Not used in backend
                postData.Add("MeetingTimeStamp", sdm.MeetingTimeStamp);
                postData.Add("PaperTimeStamp", sdm.PaperTimeStamp);
                postData.Add("CategoryTimeStamp", sdm.CategoryTimeStamp);
                postData.Add("SubCategoryTimeStamp", sdm.SubCategoryTimeStamp);
                postData.Add("HeadingTimeStamp", sdm.HeadingTimeStamp);
                postData.Add("MemberTimeStamp", sdm.MemberTimeStamp);
                postData.Add("CommentsTimeStamp", sdm.CommentTimeStamp);
                postData.Add("SecurityTimeStamp", sdm.SecurityTimeStamp);
                postData.Add("SharedDocTimeStamp", sdm.SharedDocTimeStamp);
                postData.Add("NewsItemTimeStamp", sdm.NewsItemTimeStamp);
                postData.Add("LastProfileImageSyncDateTicks", sdm.LastProfileImageSyncDateTicks);
                postData.Add("AccessesTimeStamp", sdm.AccessesTimeStamp);
                postData.Add("HeadingLastId", sdm.HeadingLastId.ToString());
                postData.Add("CommentLastId", sdm.CommentLastId.ToString());
                postData.Add("CatergoryLastId", sdm.CatergoryLastId.ToString());
                postData.Add("SubCatergoryLastId", sdm.SubCatergoryLastId.ToString());
                postData.Add("MeetingLastId", sdm.MeetingLastId.ToString());
                postData.Add("MemberLastId", sdm.MemberLastId.ToString());
                postData.Add("PaperLastId", sdm.PaperLastId.ToString());
                postData.Add("SharedDocLastId", sdm.SharedDocLastId.ToString());
                postData.Add("NewsItemLastId", sdm.NewsItemLastId.ToString());
            }
            catch (Exception)
            {
                throw;
            }
            return postData;
        }

        /// <summary>
        ///     Sync 2
        /// </summary>
        /// <param name="sdm"></param>
        /// <returns></returns>
        private Dictionary<string, string> PrepareAnnotateParameterBundle(SyncDataModel sdm)
        {
            var postData = new Dictionary<string, string>();
            try
            {
                string timeStp = sdm.SettingTimeStamp;

                if (String.IsNullOrWhiteSpace(timeStp))
                {
                    sdm.AnnotationShareId = 0;
                    sdm.SettingLastId = 0;
                }

                postData.Add("LastAnnotationShareId", sdm.AnnotationShareId.ToString());
                postData.Add("SettingLastId", sdm.SettingLastId.ToString());

                postData.Add("SettingTimeStamp",
                    String.IsNullOrWhiteSpace(timeStp) ? "0" : timeStp);
            }
            catch (Exception)
            {
                throw;
            }
            return postData;
        }

        private Dictionary<string, string> PrepareAnnotRestoreParameterBundle(SyncDataModel sdm)
        {
            var postData = new Dictionary<string, string>();
            try
            {
                string timeStp = sdm.ShareAnnotTimeStamp;

                if (String.IsNullOrWhiteSpace(timeStp))
                {
                    sdm.LastAnnotationShareId = 0;
                }

                postData.Add("lastAnnotationShareId", sdm.LastAnnotationShareId.ToString());
                postData.Add("annotationSharesTimeStamp",
                    String.IsNullOrWhiteSpace(timeStp) ? "0" : timeStp);
            }
            catch (Exception)
            {
                throw;
            }
            return postData;
        }

        public async Task<ResponseDataModel> BackupAnnotations(PaperModel data)
        {
            ResponseDataModel rdm = new ResponseDataModel();
            try
            {
                int usrid = Global.UserId;
                string usrIdW = usrid.ToString();

                LogDataModel logModel = new LogDataModel();
                logModel.Action = ApplicationConstants.LogActions.UploadAnnotation;
                logModel.MemberId = usrid;
                logModel.PaperId = data.PaperId;
                logModel.UpdateId = Guid.NewGuid().ToString();
                logModel.Status = data.VersionId.ToString();
                logModel.Data = usrIdW;
                logModel.Info = data.PaperId + "_" + usrIdW + "_" + logModel.Status + ApplicationConstants.ANNOTATEEXT; //File name

                rdm =
                                await
                                    RequestManager.CreateRequest2(GetPostData(logModel),
                                        RequestURL.UploadAnnotation + "&RefId=" + logModel.PaperId + "&type=3",
                                        logModel.Info, true);

            }
            catch (Exception)
            {
                rdm.IsError = true;
            }
            return rdm;
        }


        public async Task<List<PaperModel>> DownloadRestoreNeededAnnotationsList()
        {
            try
            {
                var sdm = await _syncDAO.GetAnnotRestoreHttpPostParameters();
                var postData = PrepareAnnotRestoreParameterBundle(sdm);

                #region Task.WhenAll

                var resultModels1 = await Task.WhenAll
                    (
                        RequestManager.CreateRequest(postData, RequestURL.RestoreAnnotationData,
                            ApplicationConstants.RequestType.POST)
                    );

                #endregion

                if (!resultModels1[0].IsError)
                {
                    var ddm1 = XmlToModelMapper.SyncDownloadDataModelMapper(resultModels1[0].Data.ToString());

                    #region Task.WhenAll

                    var resultModels2 = await Task.WhenAll
                        (
                            _syncDAO.SaveSyncDownloadDataToLocalDb(ddm1),
                            _initDAO.SyncTranckingInfoToGeneralDb(resultModels1[0])
                        );
                }
                #endregion

                return await _syncDAO.GetAnnotRestoreData();
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}